//Calculator.h: 头文件
#include <stack>
#include <vector>
#include <string>
#include <cmath>
using namespace std;

//计算器类
class Calculator
{
public:
    Calculator();
    int calculate();					//计算方法
    double getResult();					//获取结果

    int getFormat();					//表达式标准化
    int Priority(char c);				//获取算术符号优先级
    void getPostfix();					//后缀表达式转换
    int calResult();					//计算后缀表达式

    string Infix;						//输入表达式
    string stdInfix;					//标准表达式

private:
    vector<string> postfix;				//后缀表达式
    stack<char> tmpStack;				//符号栈
    stack<double> figStack;				//数字栈
    double result;						//最终计算结果

};

Calculator::Calculator() {				//构造函数，初始化成员变量
    result = 0.0;
}


//计算过程如下：
int Calculator::calculate() {
    int flag1 = getFormat();				//表达式标准化
    getPostfix();   			            //后缀表达式转换
    int flag2 = calResult();				//计算后缀表达式
    if(flag1 || flag2) {return 1;}      //如果有错就返回1 没错就返回0
    else return 0;
}

//表达式标准化
int Calculator::getFormat() {

    stdInfix = Infix;

    //去除空格
    string tmp = "";
    for (int i = 0; i < stdInfix.length(); i++) {
        if (stdInfix[i] != ' ') tmp += stdInfix[i];
    }
    stdInfix = tmp;

    //检查非法字符和括号匹配问题
    int parenthese = 0;
    for (int i = 0; i < stdInfix.length(); i++) {
        if (stdInfix[i] == '(') parenthese++;
        if (stdInfix[i] == ')') parenthese--;
        if (parenthese < 0) {
            cout << "错误：括号不匹配" << endl;
            return 1;
        }  //非法字符
        if (!(stdInfix[i] >= '0' && stdInfix[i] <= '9') && stdInfix[i] != '.' && stdInfix[i] != '+'
            && stdInfix[i] != '-' && stdInfix[i] != '*' && stdInfix[i] != '/' && stdInfix[i] != '^'
            && stdInfix[i] != '(' && stdInfix[i] != ')' && stdInfix[i] != ' ') {
            cout << "错误：输入的" << stdInfix[i] << "为非法字符" << endl;
            return 1;
        }
    }
    if (parenthese != 0) {
        cout << "错误：括号不匹配" << endl;
        return 1;
    }     //如果两侧括号不匹配，报错

    //给打头代有符号的数字前面补0
    for (int i = 0; i < stdInfix.length(); i++) {
        if (stdInfix[i] == '-' || stdInfix[i] == '+') {    //-x转换为0-x，+x转化为0+x
            if (i == 0) {
                stdInfix.insert(0, 1, '0');
            } else if (stdInfix[i - 1] == '(') {
                stdInfix.insert(i, 1, '0');
            }
        }
    }

    //给只有小数点的数字添加一个0
    for (int i = 0; i < stdInfix.length(); i++) {
        if (stdInfix[i] >= '0' && stdInfix[i] <= '9' && stdInfix[i + 1] == '.'
            && !(stdInfix[i + 2] >= '0' && stdInfix[i + 2] <= '9')) {
            stdInfix.insert(i + 2, 1, '0');
        }
    }

    //给省略乘号的算式后面补* 如 4.5（5+2） 4.5*5+2  (2+1)(3+2) (2+1)*(3+2)
    for (int i = 0; i < stdInfix.length(); i++) {
        if (((stdInfix[i] >= '0' && stdInfix[i] <= '9') || (stdInfix[i] == ')')) && stdInfix[i + 1] == '(') {
            stdInfix.insert(i+1, 1, '*');
        }
    }
    return 0;
}

//获取优先级
int Calculator::Priority(char c) {
    if (c == '+' || c == '-') {
        return 1;
    }
    else if (c == '*' || c == '/') {
        return 2;
    }
    else if (c == '^') {
        return 3;
    }
    else {
        return 0;
    }
}

//后缀表达式转换
void Calculator::getPostfix() {
    ///规则：如果符号堆顶为空或者"（"，则放入符号堆，如果符号堆堆顶元素>=当前元素，则符号栈中的元素出栈，直到条件不满足为止
    string tmp;
    for (int i = 0; i < stdInfix.length(); i++) {
            tmp = "";
        switch (stdInfix[i]) {
            case '+':
            case '-':
            case '*':
            case '/':
            case '^':
                if (tmpStack.empty() || tmpStack.top() == '(') {
                    tmpStack.push(stdInfix[i]);
                }
                else {
                    while (!tmpStack.empty() && (Priority(tmpStack.top()) >= Priority(stdInfix[i]))) {
                        tmp += tmpStack.top();
                        postfix.push_back(tmp);
                        tmpStack.pop();
                        tmp = "";
                    }
                    tmpStack.push(stdInfix[i]);
                }
                break;
            case '(':
                tmpStack.push(stdInfix[i]);
                break;
            case ')':
                while (!tmpStack.empty() && tmpStack.top() != '(') {
                    tmp += tmpStack.top();
                    postfix.push_back(tmp);
                    tmpStack.pop();
                    tmp = "";
                }
                if (!tmpStack.empty() && tmpStack.top() == '(') {
                    tmpStack.pop();							//将左括号出栈丢弃
                }
                break;
            default:
                if ((stdInfix[i] >= '0' && stdInfix[i] <= '9')) {
                    tmp += stdInfix[i];
                    while (i + 1 < stdInfix.length() && (stdInfix[i + 1] >= '0' && stdInfix[i + 1] <= '9' || stdInfix[i + 1] == '.')) {		//小数处理

                        tmp += stdInfix[i + 1];			//是连续的数字，则追加
                        i++;
                    }

                    postfix.push_back(tmp);
                }
                break;
        }
    }

    while (!tmpStack.empty()) {//将栈中剩余符号加入后缀表达式
        tmp = "";
        tmp += tmpStack.top();
        postfix.push_back(tmp);
        tmpStack.pop();
    }
}

//计算后缀表达式
int Calculator::calResult() {
    string tmp;
    double number = 0;
    double op1 = 0, op2 = 0;

    for (int i = 0; i < postfix.size(); i++) {
        tmp = postfix[i];
        if (tmp[0] >= '0' && tmp[0] <= '9') {
            number = stod(tmp);             //将字符转化为数字
            figStack.push(number);
        }
        else if (postfix[i] == "+") {
            if (!figStack.empty()) {
                op2 = figStack.top();
                figStack.pop();
            }
            if (!figStack.empty()) {
                op1 = figStack.top();
                figStack.pop();
            }
            figStack.push(op1 + op2);
        }
        else if (postfix[i] == "-") {
            if (!figStack.empty()) {
                op2 = figStack.top();
                figStack.pop();
            }
            if (!figStack.empty()) {
                op1 = figStack.top();
                figStack.pop();
            }
            figStack.push(op1 - op2);
        }
        else if (postfix[i] == "*") {
            if (!figStack.empty()) {
                op2 = figStack.top();
                figStack.pop();
            }
            if (!figStack.empty()) {
                op1 = figStack.top();
                figStack.pop();
            }
            figStack.push(op1* op2);
        }
        else if (postfix[i] == "/") {
            if (!figStack.empty()) {
                op2 = figStack.top();
                figStack.pop();
            }
            if (!figStack.empty()) {
                op1 = figStack.top();
                figStack.pop();
            }
            if (op2 == 0) {
                cout<<"错误：除数为0"<<endl;
                return 1;
            }
            figStack.push(op1 / op2);
        }

        else if (postfix[i] == "^") {
            if (!figStack.empty()) {
                op2 = figStack.top();
                figStack.pop();
            }
            if (!figStack.empty()) {
                op1 = figStack.top();
                figStack.pop();
            }
            figStack.push(pow(op1, op2));
        }
    }
    if (!figStack.empty()) {
        result = figStack.top();
    }
    return 0;
}



//获取结果
double Calculator::getResult() {
    return result;
}
